"""
# -*- coding: utf-8 -*-
# @Time    : 2023/5/24 16:28
# @Author  : 王摇摆
# @FileName: Model_Manual.py
# @Software: PyCharm
# @Blog    ：https://blog.csdn.net/weixin_44943389?type=blog
"""
import numpy as np
from sklearn.tree import DecisionTreeRegressor


class gbdtr:
    """
    梯度提升树回归算法
    """

    def __init__(self, n_estimators=100, learning_rate=0.1):
        # 梯度提升树弱学习器数量
        self.n_estimators = n_estimators
        # 学习速率
        self.learning_rate = learning_rate
        print('人工GBDT回归树已初始化完毕！')

    def fit(self, X, y): # GBDT数的训练算法
        """
        梯度提升树回归算法拟合
        """
        # 初始化 H0
        self.H0 = np.average(y)
        # 初始化预测值
        H = np.ones(X.shape[0]) * self.H0
        # 估计器数组
        estimators = []
        # 遍历 n_estimators 次
        for k in range(self.n_estimators):
            # 计算残差 y_hat
            y_hat = y - H
            # 初始化决策回归树估计器
            estimator = DecisionTreeRegressor(max_depth=3)
            # 用 y_hat 拟合训练集
            estimator.fit(X, y_hat)
            # 使用回归树的预测值
            y_predict = estimator.predict(X)
            # 更新预测值
            H += self.learning_rate * y_predict
            estimators.append(estimator)
        self.estimators = np.array(estimators)

    def predict(self, X): # GBDT推理预测
        """
        梯度提升树回归算法预测
        """
        # 初始化预测值
        H = np.ones(X.shape[0]) * self.H0
        # 遍历估计器
        for k in range(self.n_estimators):
            estimator = self.estimators[k]
            y_predict = estimator.predict(X)
            # 计算预测值
            H += self.learning_rate * y_predict
        return H
